package zhou.chs.p4_2;

import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothSocket;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class MainActivity extends AppCompatActivity  implements AdapterView.OnItemClickListener,View.OnClickListener{
    //定义控件
    ListView lv;                      //列表显示蓝牙名称及MAC地址
    TextView rxd;                      //显示接收数据
    TextView sta;                      //显示状态
    EditText txd;                       //发送数据编辑
    Button btScan, btClear,btTxd;     //按键
    //变量定义
    private BluetoothAdapter btAdapter;         //蓝牙适配器
    private BluetoothDevice btDevice;           //蓝牙设备
    BluetoothGatt btGatt;           //GATT连接
    BluetoothGattService GattS;     //GATT服务
    BluetoothGattCharacteristic Gatt_txd, Gatt_rxd; //GATT服务中的属性
    ArrayList ble_list = new ArrayList();  //蓝牙名称及MAC列表
    ArrayList bleDevices = new ArrayList(); //蓝牙列表
    ArrayAdapter madapter;  //适配器
    private boolean scan_flag;   //描述扫描蓝牙的状态
    private static final long SCAN_PERIOD = 3000;  // 蓝牙扫描时间
    private Handler mHandler;  //蓝牙扫描延时线程
    public int len;
    public String strcmd,strRec;
    private String txt,tz;
    public static String HCTXD = "0000ffe1-0000-1000-8000-00805f9b34fb";      //汇承HC08
    public static String HCRXD = "0000ffe1-0000-1000-8000-00805f9b34fb";
    public static String USRTXD = "0003cdd2-0000-1000-8000-00805f9b0131";      //有人USR-BLE101
    public static String USRRXD = "0003cdd1-0000-1000-8000-00805f9b0131";
    private static final int PERMISSION_REQUEST_COARSE_LOCATION = 1;
    private static final int REQUEST_ENABLE_BT = 1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        rxd = (TextView) findViewById(R.id.idRxd);
        sta = (TextView) findViewById(R.id.idSta);
        txd = (EditText) findViewById(R.id.idTxd);
        rxd.setMovementMethod(ScrollingMovementMethod.getInstance());
        btScan = (Button) findViewById(R.id.idScan);
        btClear = (Button) findViewById(R.id.idClear);
        btTxd = (Button) findViewById(R.id.idSend);
        btClear.setOnClickListener(this);
        btScan.setOnClickListener(this);
        btTxd.setOnClickListener(this);
        lv = (ListView) findViewById(R.id.idLv);
        lv.setOnItemClickListener(this);
        mHandler = new Handler();
        btTxd.setEnabled(false);
        // 判断硬件是否支持蓝牙
        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE))
        {
            sta.setText("不支持BLE");
            finish();
        }
        // 获取本地的蓝牙适配器，2种方法都可以
        //final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        //btAdapter = bluetoothManager.getAdapter();        //用bluetoothManager的getAdapter()方法获得蓝牙适配器
        btAdapter = BluetoothAdapter.getDefaultAdapter();  //用BluetoothAdapter的getDefaultAdapter()方法获获得蓝牙适配器
        if (btAdapter == null || !btAdapter.isEnabled())
        {       // 检查蓝牙适配器，如未打开则调用系统功能打开
            Intent enableBtIntent = new Intent(
                    BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
        }
        sta.setText("蓝牙已打开");
        scan_flag = true;
        madapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, ble_list);
        lv.setAdapter(madapter);  //通过适配器在ListView上显示配对蓝牙设备名称及MAC地址
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {     // Android6.0及以上版本动态位置权限申请
            if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);
            }
        }
    }
    //动态位置权限申请
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case PERMISSION_REQUEST_COARSE_LOCATION:
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // TODO request success
                }
                break;
        }
    }
    //响应按键单击事件
    public void onClick(View v)
    {
        switch (v.getId()) {
            case R.id.idScan:        //蓝牙扫描按钮
                if (scan_flag) {
                    bleDevices.clear();     //清空原设备列表
                    ble_list.clear();
                    madapter.notifyDataSetChanged();  //刷新列表显示
                    scanLeDevice(true);  //开始扫描
                } else {
                    scanLeDevice(false);    //停止扫描
                    btScan.setText("蓝牙扫描");
                }
                break;
            case R.id.idSend:          //发送按钮
                strcmd=txd.getText().toString();
                len=strcmd.length();
                byte[] tbuf = new byte[len/2];  // 待发送数据
                for (int i = 0; i < len; i += 2) {
                    // 两位一组，表示一个字节,把这样表示的16进制字符串，还原成一个字节
                    tbuf[i / 2] = (byte) ((Character.digit(strcmd.charAt(i), 16) << 4) + Character.digit(strcmd.charAt(i + 1), 16));
                }
                Gatt_txd.setValue(tbuf);   //向蓝牙服务中的写属性写入待发送数据
                btGatt.writeCharacteristic(Gatt_txd);  //发送数据
                break;
            case R.id.idClear:          //清空按钮
                strRec="";          //清空显示缓冲区
                rxd.setText("");    //清空显示
                break;
        }
    }
    //响应列表单击选项事件
    public void onItemClick(AdapterView<?> parent, View v, int position,long id)
    {
        TextView txv = (TextView) v;  //获取选中项文本
        String s = txv.getText().toString();
        String[] addr = s.split("\n");   //抽取MAC地址
        btDevice = btAdapter.getRemoteDevice(addr[1]);  //通过MAC地址获得蓝牙设备
        //建立GATT连接
        btGatt = btDevice.connectGatt(MainActivity.this, false, gattcallback);
        sta.setText("连接" + btDevice.getName() + "中...");
    }
    // 低功耗蓝牙扫描
    private void scanLeDevice(final boolean enable)
    {
        final BluetoothLeScanner scaner = btAdapter.getBluetoothLeScanner();
        if (enable)
        {
            mHandler.postDelayed(new Runnable()
            {
                @Override
                public void run()
                {
                    scan_flag = true;
                    btScan.setText("蓝牙扫描");
                    scaner.stopScan(mScanCallback);
                }
            }, SCAN_PERIOD);        // 扫描规定时间后停止扫描
            scan_flag = false;
            btScan.setText("停止扫描");
            scaner.startScan(mScanCallback);  // 开始扫描
        } else
        {
            scaner.stopScan(mScanCallback);   // 停止扫描
            scan_flag = true;
        }
    }
    // 返回扫描结果
    private ScanCallback mScanCallback;
    {
        mScanCallback = new ScanCallback() {
            @Override
            public void onScanResult(int callbackType, ScanResult result) {
                super.onScanResult(callbackType, result);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    BluetoothDevice device = result.getDevice();
                    if (!bleDevices.contains(device)) {  //判断是否重复
                        bleDevices.add(device);             //未重复则加入列表
                        ble_list.add(result.getDevice().getName() + "\n" + result.getDevice().getAddress());
                    }
                    madapter.notifyDataSetChanged();
                }
            }
            @Override  // 批量返回扫描结果
            public void onBatchScanResults(List<ScanResult> results) {
                super.onBatchScanResults(results);
            }
            @Override // 扫描失败
            public void onScanFailed(int errorCode) {
                super.onScanFailed(errorCode);
            }
        };
    }
    // GATT连接响应
    private BluetoothGattCallback gattcallback = new BluetoothGattCallback() {
        @Override       //GATT连接状态变化
        public void onConnectionStateChange(BluetoothGatt gatt, int status, final int newState) {
            super.onConnectionStateChange(gatt, status, newState);
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    String status;
                    switch (newState) {
                        case BluetoothGatt.STATE_CONNECTED:
                            sta.setText("已连接");
                            btGatt.discoverServices();
                            break;
                        case BluetoothGatt.STATE_CONNECTING:
                            sta.setText("正在连接");
                            break;
                        case BluetoothGatt.STATE_DISCONNECTED:
                            sta.setText("已断开");
                            break;
                        case BluetoothGatt.STATE_DISCONNECTING:
                            sta.setText("断开中");
                            break;
                    }
                }
            });
        }
        @Override  //GATT连接发现服务
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);
            txt="";
            if (status == btGatt.GATT_SUCCESS) {
                final List<BluetoothGattService> services = btGatt.getServices();
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        for (final BluetoothGattService bluetoothGattService : services) {
                            GattS = bluetoothGattService;
                            txt = txt + "\n" + GattS.getUuid().toString();   //用于显示GATT服务UUID列表
                            List<BluetoothGattCharacteristic> charc = bluetoothGattService.getCharacteristics();
                            for (BluetoothGattCharacteristic charac : charc) {
                                tz=charac.getUuid().toString();
                                txt= txt+ "\n\t" + tz ;   //用于显示GATT服务中的属性UUID列表
                                rxd.setText(txt);   //显示UUID列表
                                if ((tz.equals(HCTXD)) || (tz.equals(USRTXD))) {    //发现发送服务
                                    Gatt_txd = charac;
                                    btTxd.setEnabled(true);   //发送按钮使能，允许发送数据
                                }
                                if ((tz.equals(HCRXD)) || (tz.equals(USRRXD))) {    //发现接收服务
                                    Gatt_rxd = charac;
                                    enableNotification(true, Gatt_rxd);  //使能收到数据后通知
                                }
                            }
                        }
                    }
                });
            }
        }
        @Override   //GATT读属性
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicRead(gatt, characteristic, status);
        }
        @Override   //GATT写属性
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicWrite(gatt, characteristic, status);
        }
        @Override    //GATT属性变化，用于接收数据
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);
            final byte[] values = characteristic.getValue();
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    len=values.length;
                    for(int i=0;i<len;i++){
                        strRec = strRec + String.format("%02X",values[i]) + " ";
                    }
                    rxd.setText(strRec);
                    sta.setText("收到数据");
                }
            });
        }
        @Override   //GATT读描述
        public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorRead(gatt, descriptor, status);
        }
        @Override  //GATT写描述
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorWrite(gatt, descriptor, status);
        }
        @Override
        public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
            super.onReliableWriteCompleted(gatt, status);
        }
        @Override   //GATT读信号强度
        public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
            super.onReadRemoteRssi(gatt, rssi, status);
        }
    } ;
    // 通知参数设定
    private boolean enableNotification(boolean enable, BluetoothGattCharacteristic characteristic) {
        if (btGatt == null || characteristic == null)
            return false;
        if (!btGatt.setCharacteristicNotification(characteristic, enable))
            return false;
        BluetoothGattDescriptor clientConfig = characteristic.getDescriptor(UUID.fromString(HCRXD));
        if (clientConfig == null) clientConfig = characteristic.getDescriptor(UUID.fromString(USRRXD));;
        if (clientConfig == null)  return false;
        if (enable) {
            clientConfig.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        } else {
            clientConfig.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
        }
        return btGatt.writeDescriptor(clientConfig);
    }
    //退出前关闭蓝牙连接
    protected void onDestroy()
    {
        super.onDestroy();
        if (btGatt == null) return;
        btGatt.close();
        btGatt = null;
    }
}
